package com.opdar.platform.core.base;

import com.opdar.platform.annotations.Inject;
import com.opdar.platform.core.convert.ParameterConvert;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by shiju on 2018/2/13.
 */
public abstract class DefaultInterceptor implements Interceptor {

    private ThreadLocal<Map<String, Object>> parameters = new ThreadLocal<Map<String, Object>>();

    @Override
    public boolean before() {
        HashMap<String, Object> map = new HashMap<String, Object>();
        parameters.set(map);
        Field[] fields = getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Inject inject = field.getAnnotation(Inject.class);
            if(inject != null){
                String parameterName = field.getName();
                Map<String, String[]> parameterMap = Context.getRequest().getParameterMap();
                Type type = field.getGenericType();
                ParameterConvert<?> convert = ParameterConvertManager.getParameterConvert(type);
                try {
                    if (convert != null) {
                        Object value = convert.convert(parameterMap.get(parameterName));
                        field.set(this, value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return preHandle();
    }


    public abstract boolean preHandle();

    public abstract boolean postHandle();

    public abstract void afterCompletion();

    @Override
    public boolean after() {
        return postHandle();
    }

    @Override
    public void finish() {
        try {
            afterCompletion();
        } finally {
            clearField();
            parameters.remove();
        }
    }

    private void clearField() {
        Field[] fields = getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Inject inject = field.getAnnotation(Inject.class);
            if (inject != null) {
                try {
                    field.set(this,null);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public Map<String, Object> getParameters() {
        return parameters.get();
    }

    public void addParameter(String key, Object value) {
        parameters.get().put(key, value);
    }
}
